package errors

import (
	"errors"
	"fmt"
	"os"
)

// 自定义错误类型
// DivideByZeroError 表示除以零的错误
type DivideByZeroError struct {
	Dividend float64
	Divisor  float64
}

// 实现error接口
func (e DivideByZeroError) Error() string {
	return fmt.Sprintf("除数不能为零: %f / %f", e.Dividend, e.Divisor)
}

// ValidatePositive 验证数字是否为正数
// 如果不是正数，返回自定义错误
func ValidatePositive(num float64) error {
	if num <= 0 {
		return fmt.Errorf("数字必须为正数，当前值: %.2f", num)
	}
	return nil
}

// SafeDivide 安全的除法操作，返回可能的错误
func SafeDivide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, &DivideByZeroError{Dividend: a, Divisor: b}
	}
	return a / b, nil
}

// DemoDefer 演示defer的使用
func DemoDefer() {
	fmt.Println("开始演示defer...")

	// defer语句会在函数返回前执行
	defer fmt.Println("defer 1: 这将在函数结束时执行")
	defer fmt.Println("defer 2: 这也将在函数结束时执行")

	// defer是后进先出(LIFO)的顺序执行
	fmt.Println("函数正在执行...")

	// defer可以用于资源清理
	file, err := os.Create("temp.txt")
	if err != nil {
		fmt.Println("创建文件失败:", err)
		return
	}
	defer func() {
		file.Close()
		os.Remove("temp.txt") // 清理临时文件
		fmt.Println("defer: 文件已关闭并删除")
	}()

	// 写入一些内容到文件
	data := []byte("这是临时数据")
	n, err := file.Write(data)
	if err != nil {
		fmt.Println("写入文件失败:", err)
		return
	}
	fmt.Printf("写入了%d字节到文件\n", n)
}

// DemoPanicRecover 演示panic和recover的使用
func DemoPanicRecover() {
	fmt.Println("开始演示panic和recover...")

	// 使用defer和recover捕获panic
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("捕获到panic: %v\n", r)
		}
	}()

	// 正常执行
	fmt.Println("函数正常执行中...")

	// 触发panic
	panic("故意触发的panic")

	// 下面的代码不会执行
	// fmt.Println("这行代码不会被执行")
}

// NestedPanic 演示嵌套函数中的panic和recover
func NestedPanic() {
	fmt.Println("开始演示嵌套函数中的panic和recover...")

	// 外部defer不会捕获内部函数的panic
	defer func() {
		fmt.Println("外部defer执行")
	}()

	// 内部函数
	innerFunction := func() {
		// 内部defer捕获panic
		defer func() {
			if r := recover(); r != nil {
				fmt.Printf("内部函数捕获到panic: %v\n", r)
			}
		}()

		panic("内部函数触发的panic")
	}

	innerFunction()

	// 内部函数的panic被捕获后，外部函数继续执行
	fmt.Println("内部函数执行完毕，外部函数继续执行")
}

// DemoErrorHandling 展示错误处理机制
func DemoErrorHandling() {
	fmt.Println("=== 错误处理演示 ===")

	// 1. 基本错误处理
	fmt.Println("\n--- 基本错误处理 ---")
	result, err := SafeDivide(10, 2)
	if err != nil {
		fmt.Println("除法错误:", err)
	} else {
		fmt.Printf("10 / 2 = %.2f\n", result)
	}

	// 除以零错误
	result, err = SafeDivide(5, 0)
	if err != nil {
		fmt.Println("除法错误:", err)
		// 类型断言，检查错误类型
		if divErr, ok := err.(*DivideByZeroError); ok {
			fmt.Printf("被除数: %.2f, 除数: %.2f\n", divErr.Dividend, divErr.Divisor)
		}
	}

	// 使用errors.New创建错误
	err = errors.New("这是一个普通错误")
	fmt.Println("错误信息:", err)

	// 使用fmt.Errorf创建格式化错误
	err = fmt.Errorf("错误码: %d, 消息: %s", 404, "未找到资源")
	fmt.Println("格式化错误:", err)

	// 2. defer语句演示
	fmt.Println("\n--- defer语句演示 ---")
	DemoDefer()

	// 3. panic和recover演示
	fmt.Println("\n--- panic和recover演示 ---")
	DemoPanicRecover()

	// 4. 嵌套函数中的panic和recover
	fmt.Println("\n--- 嵌套函数中的panic和recover ---")
	NestedPanic()

	// 5. 验证函数中的错误处理
	fmt.Println("\n--- 验证函数中的错误处理 ---")
	err = ValidatePositive(-5)
	if err != nil {
		fmt.Println("验证错误:", err)
	} else {
		fmt.Println("验证通过")
	}

	// 验证通过的情况
	err = ValidatePositive(10)
	if err != nil {
		fmt.Println("验证错误:", err)
	} else {
		fmt.Println("验证通过")
	}
}
